#lang racket/base
(provide
 check-expansion
 check-expansion-exn
 check-identity-expansion)

(require
 (for-syntax
  racket/base
  syntax/parse)
 rackunit)

(begin-for-syntax
  (define (simple-expand stx)
    (local-expand stx 'expression '())))

(define-syntax check-expansion
  (syntax-parser
    [(_ to-expand templ)
     #'(check-expansion to-expand
                        templ
                        simple-expand)]

    [(_ to-expand templ expand-func)
     #'(check-expansion to-expand
                        #:no-quote `templ
                        expand-func)]

    [(_ to-expand #:no-quote templ expand-func)
     #:with [tmp-m] (generate-temporaries #'[mac])
     #'(begin
         (define-syntax (tmp-m stx)
           #`'#,(expand-func (syntax-local-introduce #'to-expand)))
         (check-match (tmp-m)
                      templ))]))

(define-syntax check-expansion-exn
  (syntax-parser
    [(_ to-expand exn-pred)
     #'(check-expansion-exn to-expand
                            exn-pred
                            simple-expand)]

    [(_ to-expand exn-pred expand-func)
     #:with [tmp-m] (generate-temporaries #'[mac])
     #'(begin
         (define-syntax (tmp-m stx)
           (with-handlers
             ([exn? (λ (e) #`(error '#,(exn-message e)))])
             #`'#,(expand-func #'to-expand)))
         (check-exn exn-pred (λ () (tmp-m))))]))

(define-syntax-rule (check-identity-expansion term expand-func)
  (check-expansion term term expand-func))
